package com.sk.extension.controller;

import com.sk.extension.constants.Constant;
import jakarta.annotation.Resource;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
@RequestMapping("/producer")
public class ProducerController {

    @Resource(name = "rabbitTemplate")
    private RabbitTemplate rabbitTemplate;

    @Resource(name = "confirmRabbitTemplate")
    private RabbitTemplate confirmRabbitTemplate;

    @Resource(name = "transRabbitTemplate")
    private RabbitTemplate transRabbitTemplate;

    @RequestMapping("/ack")
    public String ack() {
        rabbitTemplate.convertAndSend(Constant.ACK_EXCHANGE_NAME, "ack", "consumer ack test...");
        return "发送成功!";
    }

    @RequestMapping("/pres")
    public String pres() {
        Message message = new Message("Presistent test...".getBytes(), new MessageProperties());
        //消息非持久化
        message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);
        //消息持久化
//        message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
        System.out.println(message);
        rabbitTemplate.convertAndSend(Constant.PRES_EXCHANGE, "pres", message);
        return "消息发送成功";
    }

    //这种写法存在两个问题：
    //1. 这种方式设置ConfirmCallback影响所有rabbit template，因为默认注入的是单例的
    //2. 重复调用会报错
    //解决方式：创建一个新的类，使用多例
//    @RequestMapping("/confirm")
//    public String confirm() {
//        //设置回调方法
//        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
//            @Override
//            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
//                System.out.println("执行了Confirm...");
//                if (ack){
//                    System.out.printf("消息接收成功, id:%s \n", correlationData.getId());
//                }else{
//                    System.out.printf("未接收到消息, 消息ID: %s, cause: %s", correlationData.getId(), cause);
//                }
//
//            }
//        });
//        CorrelationData correlationData = new CorrelationData("1");
//        rabbitTemplate.convertAndSend(Constant.CONFIRM_EXCHANGE,"confirm","confirm test...",correlationData);
//        return "消息发送成功";
//    }
    @RequestMapping("/confirm")
    public String confirm() {
        CorrelationData correlationData = new CorrelationData("1");
        confirmRabbitTemplate.convertAndSend(Constant.CONFIRM_EXCHANGE, "confirm111", "confirm test...", correlationData);
        return "消息发送成功";
    }

    @RequestMapping("/returns")
    public String returns() {
        CorrelationData correlationData = new CorrelationData("5");
        confirmRabbitTemplate.convertAndSend(Constant.CONFIRM_EXCHANGE, "confirm111", "returns test...", correlationData);
        return "消息发送成功";
    }

    @RequestMapping("/retry")
    public String retry() {
        System.out.println("retry...");
        rabbitTemplate.convertAndSend(Constant.RETRY_EXCHANGE, "retry", "retry test...");
        return "消息发送成功";
    }

    //1. 设置消息TTL
    @RequestMapping("/ttl")
    public String ttl() {
        System.out.println("ttl...");
//        MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
//            @Override
//            public Message postProcessMessage(Message message) throws AmqpException {
//                //设置过期时间：单位 毫秒
//                message.getMessageProperties().setExpiration("10000");
//                return null;
//            }
//        };
//        rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE, "ttl", "ttl test 30s...",messagePostProcessor);

        rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE, "ttl", "ttl test 30s...", message -> {
            message.getMessageProperties().setExpiration("30000");  //单位: 毫秒, 过期时间为30s
            return message;
        });

        rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE, "ttl", "ttl test 10s...", message -> {
            message.getMessageProperties().setExpiration("10000");  //单位: 毫秒, 过期时间为10s
            return message;
        });
        return "消息发送成功";
    }

    @RequestMapping("/ttl2")
    public String ttl2() {
        System.out.println("ttl2...");
        //发送普通消息
        rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE, "ttl", "ttl test...");
        return "消息发送成功";
    }

    @RequestMapping("/dl")
    public String dl() {
        System.out.println("dl...");
        //发送普通消息
        rabbitTemplate.convertAndSend(Constant.NORMAL_EXCHANGE, "normal", "dl test...");
        System.out.printf("%tc 消息发送成功 \n", new Date());
//        //测试队列长度
//        for (int i = 0; i < 20; i++) {
//            rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE, "normal", "dl test..."+i);
//        }
        return "消息发送成功";
    }

    @RequestMapping("/delay2")
    public String delay2() {
        System.out.println("delay2...");

        rabbitTemplate.convertAndSend(Constant.DELAY_EXCHANGE, "delay", "delay test 30s...", message -> {
            //上面设置的是过期时间，这里设置的是延迟时间
            message.getMessageProperties().setDelayLong(30000L);  //单位: 毫秒, 过期时间为30s
            return message;
        });
        rabbitTemplate.convertAndSend(Constant.DELAY_EXCHANGE, "delay", "delay test 10s...", message -> {
            message.getMessageProperties().setDelayLong(10000L);  //单位: 毫秒, 延迟时间为10s
            return message;
        });

        System.out.printf("%tc 消息发送成功 \n", new Date());
        return "消息发送成功";
    }

    @Transactional
    @RequestMapping("/trans")
    public String trans(){
        //1. rabbitTemplate.setChannelTransacted(true);设置事务属性为true
        //2. 开启@Transactional注解
        //3. RabbitTransactionManager
        System.out.println("trans test...");
        transRabbitTemplate.convertAndSend("",Constant.TRANS_QUEUE, "trans test 1...");
        int num = 5/0;
        transRabbitTemplate.convertAndSend("",Constant.TRANS_QUEUE, "trans test 2...");
        return "消息发送成功";
    }

    //限流发送
    @RequestMapping("/qos")
    public String qos() {
        System.out.println("qos test...");
        //发送普通消息
        for (int i = 0; i < 20; i++) {
            rabbitTemplate.convertAndSend(Constant.QOS_EXCHANGE, "qos", "qos test..."+i);
        }
        return "消息发送成功";
    }

}
